/*  This file is part of Real Time Digital Audio Processing library.
 *  Copyright (C) 2008 - Emilio Monti - emilmont@gmail.com
 *
 *  Real Time Digital Audio Processing library is free software: you can
 *  redistribute it and/or modify it under the terms of the GNU General
 *  Public License as published by the Free Software Foundation, either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  Real Time Digital Audio Processing library is distributed in the hope
 *  that it will be useful, but WITHOUT ANY WARRANTY; without even the
 *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Real Time Audio Processing library.
 *  If not, see <http://www.gnu.org/licenses/>.
 */
#include <math.h>

#include "DTMF.h"

#define DTMF_WINDOW   205

DTMF::DTMF(unsigned int sampleRate, float amp, char tone) {
    unsigned int f[2];
    switch (tone) {
        case '1': case '2': case '3': f[0] = DTMF_FREQ[0]; break;
        case '4': case '5': case '6': f[0] = DTMF_FREQ[1]; break;
        case '7': case '8': case '9': f[0] = DTMF_FREQ[2]; break;
        case '*': case '0': case '#': f[0] = DTMF_FREQ[3]; break;
    }
    switch (tone) {
        case '1': case '4': case '7': case '*': f[1] = DTMF_FREQ[4]; break;
        case '2': case '5': case '8': case '0': f[1] = DTMF_FREQ[5]; break;
        case '3': case '6': case '9': case '#': f[1] = DTMF_FREQ[6]; break;
    }
    sprintf(descr, "[+] DTMF %c (%uHz, %uHz)", tone, f[0], f[1]);
    s[0] = new Sine(sampleRate, amp, f[0]);
    s[1] = new Sine(sampleRate, amp, f[1]);
}

void DTMF::processSignal(float* signal, unsigned long length) {
    s[0]->processSignal(signal, length);
    s[1]->processSignal(signal, length);
}

DTMF::~DTMF() {
    delete s[0];
    delete s[1];
}

DTMF_Detector::DTMF_Detector(unsigned int sampleRate) {
    sprintf(descr, "[=] DTMF_Detector");
    for (int i=0; i<7; i++) {

        c[i] = 2.0*cos(2.0*PI*(float)DTMF_FREQ[i]/(float)sampleRate);
        for (int j=0; j<3; j++) {
            d[i][j] = 0.0;
        }
    }

    index = 0;
}

void DTMF_Detector::processSignal(float* signal, unsigned long length) {
    for (unsigned long int i=0; i<length; i++) {
        for (int j=0; j<7; j++) {
            d[j][0]=signal[i]+c[j]*d[j][1]-d[j][2];
            d[j][2]=d[j][1];
            d[j][1]=d[j][0];
        }

        if (index++ > DTMF_WINDOW) {
            for (int k=0; k<7; k++) {
                r[k]= d[k][1]*d[k][1] - c[k]*d[k][1]*d[k][2] + d[k][2]*d[k][2];
                d[k][1]=0;
                d[k][2]=0;
            }
            index = 0;
        }
    }
}

char DTMF_Detector::detected(void) {
    int lf_index, hf_index;
    double max = 0.0;
    for (int i=0; i<4; i++) {
        if (r[i]>max) {
            max = r[i];
            lf_index = i;
        }
    }
    max = 0.0;
    for (int i=4; i<7; i++) {
        if (r[i]>max) {
            max = r[i];
            hf_index = i;
        }
    }
    return DTMF_KEYS[lf_index][hf_index-4];
}
